package com.goa.parse;

/**
 * Modbus响应报文校验（使用中）
 */
public class VerificationData {


    /**
     * 整合校验方法
     * @param response 响应报文
     * @return 全部校验通过。则返回true，否则返回false
     */
    public static boolean checkHex16(byte[] response){
        if (checkLength(response)&&checkCRC(response)){
            return true;
        }
        return false;
    }

    /**
     * 响应报文位数校验
     * @param response 响应报文
     * @return 如果位数正确，则返回true，否则返回false
     */
    public static boolean checkLength(byte[] response) {
        // Modbus报文长度必须在特定范围内
        // 根据具体协议定义，添加逻辑
        System.out.println("response = " + response.length);
        return response.length > 0 && response.length <= 256; // 示例长度限制
    }

    /**
     * 响应报文偶数校验
     * @param response 响应报文
     * @return 如果报文偶数位数，则返回true，否则返回false
     */
    public static boolean checkEven(byte[] response) {
        return response.length % 2 == 0;
    }

    /**
     * 校验报文CRC校验
     * @param response 响应报文
     * @return 如果CRC校验通过，则返回true，否则返回false
     */
    public static boolean checkCRC(byte[] response) {
        if (response.length < 3) { // CRC需要至少两个字节
            return false;
        }
        int crc = calculateCRC(response, response.length - 2); // 计算CRC，排除最后两个字节
        int receivedCRC = (response[response.length - 2] & 0xFF) | ((response[response.length - 1] & 0xFF) << 8);
        return crc == receivedCRC;
    }

    /**
     * 计算CRC值
     * @param data 数据数组
     * @param length 数据长度
     * @return 返回计算得到的CRC值
     */
    private static int calculateCRC(byte[] data, int length) {
        int crc = 0xFFFF; // 初始化CRC值
        for (int i = 0; i < length; i++) {
            crc ^= (data[i] & 0xFF);
            for (int j = 0; j < 8; j++) {
                if ((crc & 0x0001) != 0) {
                    crc = (crc >> 1) ^ 0xA001; // 多项式
                } else {
                    crc = crc >> 1;
                }
            }
        }
        return crc;
    }
}
